﻿using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using System.Xml;

public class GameMapsManager
{
    GameMapsManager _Inst;
    public GameMapsManager Inst { get { if (_Inst == null) { _Inst = new GameMapsManager(); } return _Inst; } }
    Dictionary<int, GameMapData> Maps = new Dictionary<int, GameMapData>();

}


public class GameMapData
{
    public int MapId;
    public string MapPath;

    #region MapHeader
    public class GameMapDataHeader
    {
        public string MapName;
        public string MapPath;
        public string MapDesc;
        public string ScriptPath;
        public int MapWidth;
        public int MapHeight;
        public int TileSizeX;
        public float HalfSzieX { get { return (float)TileSizeX / 2; } }
        public int TilesizeY;
        public float HalfSzieY { get { return (float)TilesizeY / 2; } }
        public GameMapDataHeader() { }
        public GameMapDataHeader(GameMapDataHeader header)
        {
            this.MapName = header.MapName;
            this.MapPath = header.MapPath;
            this.MapDesc = header.MapDesc;
            this.ScriptPath = header.ScriptPath;
            this.MapWidth = header.MapWidth;
            this.MapHeight = header.MapHeight;
            this.TileSizeX = header.TileSizeX;
            this.TilesizeY = header.TilesizeY;
        }
        public GameMapDataHeader(XmlElement elem)
        {
            this.MapName = elem.Attributes["MapName"].Value;
            this.MapPath = elem.Attributes["MapPath"].Value;
            this.MapDesc = elem.Attributes["Desc"].Value;
            if (elem.Attributes["Script"] != null)
            {
                this.ScriptPath = elem.Attributes["Script"].Value;
            }
            this.TileSizeX = int.Parse(elem.Attributes["TileSizeX"].Value);
            this.TilesizeY = int.Parse(elem.Attributes["TileSizeY"].Value);
            this.MapWidth = int.Parse(elem.Attributes["TileWidth"].Value);
            this.MapHeight = int.Parse(elem.Attributes["TileHeight"].Value);


        }
        public XmlElement ToXml(XmlElement headerElem)
        {
            /* MapName="掉砖块测试" MapPath="" Desc="掉砖块测试用地图" TileWidth="20" TileHeight="10"
            Gravity="0,-1200" TileSizeX="50" TileSizeY="50"  Script="Map/testMapLogic.js"*/
            headerElem.SetAttribute("MapName", this.MapName);
            headerElem.SetAttribute("MapPath", this.MapPath);
            headerElem.SetAttribute("Desc", this.MapDesc);
            headerElem.SetAttribute("TileWidth", this.MapWidth.ToString());
            headerElem.SetAttribute("TileHeight", this.MapHeight.ToString());
            headerElem.SetAttribute("TileSizeX", this.TileSizeX.ToString());
            headerElem.SetAttribute("TileSizeY", this.TilesizeY.ToString());
            headerElem.SetAttribute("Script", this.ScriptPath);
            return headerElem;
        }
    }

    public GameMapDataHeader Header;
    #endregion


    #region LayerData
    public class MapLayerData
    {
        public GameMapData mapData;

        public MapBlock[,] MapBlocks;
        public int Id;
        public string Desc;
        public MapLayerData() { }

        public MapLayerData(XmlElement elem, GameMapData data)
        {
            this.mapData = data;
            this.MapBlocks = new MapBlock[data.Header.MapHeight, data.Header.MapWidth];

            this.Id = int.Parse(elem.Attributes["Id"].Value);
            if (elem.Attributes["Desc"] != null)
            {
                this.Desc = elem.Attributes["Desc"].Value;
            }
            string[] strBlocks = elem.InnerText.Replace("\r", "").Replace("\n", "").Replace(" ", "").Split(',');
            for (int y = 0; y < data.Header.MapHeight; y++)
            {
                for (int x = 0; x < data.Header.MapWidth; x++)
                {
                    int blockIndex = int.Parse(strBlocks[y * data.Header.MapWidth + x]);
                    this.AddBlock(blockIndex, x, data.Header.MapHeight - 1 - y);
                }
            }
        }

        public int GetBlockIndex(int y, int x)
        {
            if (MapBlocks[y, x] == null)
            {
                return -1;
            }
            return MapBlocks[y, x].StaticBlockIndex;
        }


        public void AddBlock(int index, int x, int y)
        {
            if (index == -1)
            {
                MapBlocks[y, x] = null;
                return;
            }
            MapStaticBlock staticBlock = MapBlockData.Inst.Blocks[index];
            MapBlock mapBlock = new MapBlock(staticBlock.Id, x, y);
            for (int yi = 0; yi < staticBlock.Heigth; yi++)
            {
                for (int xi = 0; xi < staticBlock.Width; xi++)
                {
                    int newX = x + xi;
                    int newY = y + yi;
                    if (newX < mapData.Header.MapWidth && newY < mapData.Header.MapHeight)
                    {
                        MapBlocks[newY, newX] = mapBlock;
                    }
                }
            }
            return;
        }

        public void RemoveBlock(int x, int y)
        {
            if (MapBlocks[y, x] == null)
            {
                return;
            }
            MapBlock block = MapBlocks[y, x];
            for (int yi = 0; yi < block.StaticBlock.Heigth; yi++)
            {
                for (int xi = 0; xi < block.StaticBlock.Width; xi++)
                {
                    MapBlocks[block.PosY + yi, block.PosX + xi] = null;
                }
            }
        }

        public XmlElement ToXml(XmlElement elem)
        {
            elem.SetAttribute("Id", this.Id.ToString());
            elem.SetAttribute("Desc", this.Desc);
            string StrBock = "";
            for (int y = 0; y < mapData.Header.MapHeight; y++)
            {
                for (int x = 0; x < mapData.Header.MapWidth; x++)
                {
                    string endExt = y == mapData.Header.MapHeight - 1 && x == mapData.Header.MapWidth - 1 ? "" : ",";
                    int newY = mapData.Header.MapHeight - y - 1;
                    MapBlock CurBlock = MapBlocks[newY, x];
                    if (CurBlock != null && CurBlock.PosX == x && CurBlock.PosY == newY)
                    {
                        StrBock += CurBlock.StaticBlockIndex.ToString() + endExt;
                    }
                    else
                    {
                        StrBock += "-1" + endExt;
                    }

                }
            }
            elem.InnerText = StrBock.Substring(0, StrBock.Length);
            return elem;
        }
    }
    #endregion

    public MapLayerData[] LayerDatas;

    public int CurEditLayout = 0;

    public GameMapData()
    {
        this.Header = new GameMapDataHeader();
    }

    public static GameMapData Inst { get; set; }

    public GameMapData(string filePath)
    {
        XmlDocument xmlDoc = new XmlDocument();
        xmlDoc.Load(filePath);
        this.Header = new GameMapDataHeader(xmlDoc.SelectSingleNode("Map/MapHeader") as XmlElement);
        XmlNode LayerNodes = xmlDoc.SelectSingleNode("Map/MapBlockLayers");
        this.LayerDatas = new MapLayerData[LayerNodes.ChildNodes.Count];

        for (int i = 0; i < this.LayerDatas.Length; i++)
        {
            this.LayerDatas[i] = new MapLayerData(LayerNodes.ChildNodes[i] as XmlElement, this);
        }
        Inst = this;
    }
}



